/// ****************************************************************************
/// Author:	        Robin Zhu
/// Create Date:	2012-1-4
/// Purpose: 		类型操作工具类文件
/// ****************************************************************************
/// Modify By		Date			Remark
/// Robin           2013-4-15       使用Convert.ChangeType避免类型不兼容
/// Robin           2013-4-16       在Convert.ChangeType前判断类型是否为泛型
/// Robin           2013-4-18       修复ConvertField<T>在转换枚举型时出错的Bug
/// Robin           2013-7-1        防止在Convert一个Nullabe的枚举时出现Bug
/// ****************************************************************************


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;

namespace RB.DataAccess
{
    /// <summary>
    /// 类型操作工具类，对系统的类型操作进行补充
    /// </summary>
    internal static class TypeSystem
    {
        internal static Type GetElementType(Type seqType)
        {
            Type ienum = FindIEnumerable(seqType);
            if (ienum == null) return seqType;
            return ienum;
        }

        private static Type FindIEnumerable(Type seqType)
        {
            if (seqType == null || seqType == typeof(string))
                return null;
            if (seqType.IsArray)
                return seqType.GetElementType();
            if (seqType.IsGenericType)
            {
                foreach (Type arg in seqType.GetGenericArguments())
                {
                    Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
                    if (ienum.IsAssignableFrom(seqType))
                    {
                        return arg;
                    }
                }
            }
            Type[] ifaces = seqType.GetInterfaces();
            if (ifaces != null && ifaces.Length > 0)
            {
                foreach (Type iface in ifaces)
                {
                    Type ienum = FindIEnumerable(iface);
                    if (ienum != null) return ienum;
                }
            }
            if (seqType.BaseType != null && seqType.BaseType != typeof(object))
            {
                return FindIEnumerable(seqType.BaseType);
            }
            return null;
        }

        internal static object ConvertField(object fieldValue, Type type)
        {
            if (fieldValue != null && !Convert.IsDBNull(fieldValue))
            {
                if (type == typeof(string))
                {
                    return fieldValue.ToString().TrimEnd();
                }
                else
                {
                    if (type.IsGenericType)
                    {
                        type = type.GetGenericArguments()[0];
                    }
                    if (type.IsEnum)
                    {
                        return Enum.ToObject(type, fieldValue);
                    }
                    return Convert.ChangeType(fieldValue, type);

                    //else if (typeof(IConvertible).IsAssignableFrom(type))
                    //{
                    //    try
                    //    {
                    //        return Convert.ChangeType(fieldValue, type);
                    //    }
                    //    catch
                    //    {
                    //    }
                    //}
                    //else
                    //{
                    //    try
                    //    {
                    //        return Activator.CreateInstance(type, fieldValue);
                    //    }
                    //    catch
                    //    {
                    //    }
                    //}
                }
            }
            // 返回默认值或空值
            return GetDefaultValue(type);
        }

        private static object GetDefaultValue(Type type)
        {
            if (type.IsValueType && !IsNullableType(type))
            {
                if (type.IsPrimitive)
                {
                    if (type == typeof(bool))
                        return false;
                    else
                        return Convert.ChangeType(0, type);
                }
                else
                {
                    if (type == typeof(DateTime))
                        return default(DateTime);
                    else if (type == typeof(Guid))
                        return default(Guid);
                    else
                        return Activator.CreateInstance(type);
                }
            }
            else
                return null;
        }

        internal static T ConvertField<T>(object fieldValue)
        {
            if (fieldValue != null && !Convert.IsDBNull(fieldValue))
            {
                Type type = typeof(T);
                if (type.IsEnum)
                {
                    return (T)Enum.ToObject(type, fieldValue);
                }
                else if (type.IsGenericType)
                {
                    type = type.GetGenericArguments()[0];
                }
                return (T)Convert.ChangeType(fieldValue, type);
            }
            return default(T);
        }

        internal static bool IsNullableType(Type t)
        {
            return Nullable.GetUnderlyingType(t) != null;
        }
    }
}
